package com.qn.validation.helper;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import com.qn.validation.annotation.AssertTrueOn;
import com.qn.validation.annotation.EnableCondition;
import com.qn.validation.annotation.NotNullOn;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Map;

/**
 * 条件验证器
 *
 * @author QN
 * @date 2024/12/30
 */
public class ConditionValidator implements ConstraintValidator<EnableCondition, Object> {

    private static final ExpressionParser PARSER = new SpelExpressionParser();
    private static final EvaluationContext EL_CONTEXT = new StandardEvaluationContext();

    @Override
    public boolean isValid(Object validatedBean, ConstraintValidatorContext context) {
        // 将对象转换为map
        Map<String, Object> map = BeanUtil.beanToMap(validatedBean);
        map.forEach(EL_CONTEXT::setVariable);

        // 校验对象字段上是否有NotNullOn注解，如果有，则执行校验逻辑
        Field[] fields = ReflectUtil.getFields(validatedBean.getClass());

        boolean res = true;
        for (Field field : fields) {
            // 获取当前字段名称
            String fieldName = field.getName();
            // 获取当前字段值
            Object fieldValue = ReflectUtil.getFieldValue(validatedBean, field.getName());
            // 获取当前字段注解
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof NotNullOn notNullOn) {
                    res = res && isValid(NotNullOn.class.getName(), fieldName, fieldValue, notNullOn.on(), notNullOn.message(), context);
                }
                if (annotation instanceof AssertTrueOn assertTrueOn) {
                    res = res && isValid(AssertTrueOn.class.getName(), fieldName, fieldValue, assertTrueOn.on(), assertTrueOn.message(), context);
                }
            }
        }
        return res;
    }

    /**
     * 校验字段值是否为空
     *
     * @param annotationType 注解类型
     * @param fieldName      字段名
     * @param fieldValue     字段值
     * @param on             el条件表达式
     * @param message        提示信息
     * @param context        校验上下文
     * @return boolean
     */
    boolean isValid(String annotationType, String fieldName, Object fieldValue, String on, String message, ConstraintValidatorContext context) {
        boolean res = true;
        // 解析on属性值，如果解析结果为true，则执行NotNullValidator校验
        if (parseEl(on)) {
            // 校验字段值是否为空
            ConstraintValidator validator = SupportContext.getValidator(annotationType);
            if (!validator.isValid(fieldValue, context)) {
                res = false;
                context.buildConstraintViolationWithTemplate(message)
                        .addPropertyNode(fieldName)
                        .addConstraintViolation();
            }
        }
        return res;
    }

    /**
     * 解析el表达式
     *
     * @param el 埃尔
     * @return {@link Boolean }
     */
    private static Boolean parseEl(String el) {
        Expression expression = PARSER.parseExpression(el);
        return expression.getValue(EL_CONTEXT, Boolean.class);
    }

}
